﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using KylinORM.Data;
using System.Reflection;
using KylinORM.Mapper.Base;
using KylinORM.Aspect.Definition;
using System.Linq.Expressions;

namespace KylinORM.Utils
{
    /// <summary>
    /// 类型转换
    /// </summary>
    internal abstract class TypeConverter
    {
        #region DataTable转DTO
        /// <summary>
        /// DataRow转数据传输对象
        /// </summary>
        /// <typeparam name="T">数据传输对象类型</typeparam>
        /// <param name="dr">数据源</param>
        /// <returns></returns>
        internal static T GetEntity<T>(DataRow dr) where T : new()
        {
            object newT = new T();
            PropertyInfo[] infos = typeof(T).GetProperties();

            foreach (DataColumn dc in dr.Table.Columns)
            {
                PropertyInfo info = infos.Where(d => d.Name == dc.ColumnName).FirstOrDefault();
                if (info != null)
                {
                    if (info.PropertyType.FullName != "System.String" && !info.PropertyType.IsValueType)
                        continue;

                    info.SetValue(newT, dr[dc.ColumnName] == DBNull.Value ? null : dr[dc.ColumnName], null);
                }
            }
            return (T)newT;
        }

        /// <summary>
        /// DataTable转数据传输对象
        /// </summary>
        /// <typeparam name="T">数据传输对象类型</typeparam>
        /// <param name="dt">数据源</param>
        /// <returns></returns>
        internal static List<T> GetEntityList<T>(DataTable dt) where T : new()
        {
            List<T> list = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(GetEntity<T>(dr));
            }
            return list;
        }
        #endregion

        #region DataTable转实体
        /// <summary>
        /// DataRow转实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dr">数据源</param>
        /// <param name="mapper">实体映射器，转换时会应用此规则</param>
        /// <returns></returns>
        internal static T GetEntity<T>(DataRow dr, IMapper mapper) where T : new()
        {
            T newT = new T();
            foreach (DataColumn dc in dr.Table.Columns)
            {
                EntityFieldInfo fieldInfo = mapper.EntityFieldInfos.Values.Where(d => d.FieldName == dc.ColumnName).FirstOrDefault();
                if (fieldInfo != null)
                {
                    fieldInfo.PropertyInfo.SetValue(newT, dr[dc.ColumnName] == DBNull.Value ? null : dr[dc.ColumnName], null);
                }
            }
            return newT;
        }

        /// <summary>
        /// DataTable转实体列表
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="dt">数据源</param>
        /// <param name="mapper">实体映射器，转换时会应用此规则</param>
        /// <returns></returns>
        internal static List<T> GetEntityList<T>(DataTable dt, IMapper mapper) where T : new()
        {
            List<T> list = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(GetEntity<T>(dr, mapper));
            }
            return list;
        }
        #endregion

        #region MethodInfo转Delegate
        /// <summary>
        /// 创建委托以表示指定的方法
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        internal static Delegate CreateDelegate(MethodInfo method)
        {
            if (method == null) throw new ArgumentNullException("method");

            if (method.IsStatic)
                return CreateDelegate(method, null);
            else
                return CreateDelegate(method, Activator.CreateInstance(method.ReflectedType));
        }
        /// <summary>
        /// 创建委托以表示指定的方法
        /// </summary>
        internal static Delegate CreateDelegate(MethodInfo method, object target)
        {
            if (method == null) throw new ArgumentNullException("method");

            Type delegateType;

            var typeArgs = method.GetParameters()
                .Select(p => p.ParameterType)
                .ToList();

            // 获得委托类型
            if (method.ReturnType == typeof(void))
            {
                delegateType = Expression.GetActionType(typeArgs.ToArray());

            }
            else
            {
                typeArgs.Add(method.ReturnType);
                delegateType = Expression.GetFuncType(typeArgs.ToArray());
            }

            // 调用静态方法或实例的方法
            var result = (target == null)
                ? Delegate.CreateDelegate(delegateType, method)
                : Delegate.CreateDelegate(delegateType, target, method);

            return result;
        }
        #endregion

        #region 类型判断
        /// <summary>
        /// 目标类型是否为整数
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        internal static bool IsNumberType(Type type)
        {
            Type[] types = { typeof(int?), typeof(int), typeof(long?), typeof(long) };
            return types.Contains(type);
        }
        /// <summary>
        /// 目标类型是否为值类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        internal static bool IsValueType(Type type)
        {
            return type.FullName == "System.String" || type.IsValueType;
        }
        #endregion

    }
}
